#!/usr/bin/env node
/**
 * 手动打包VSCode插件为VSIX文件
 * 解决Node.js v19.9.0与vsce工具的兼容性问题
 * @author lihengtt <lihengsir@gmail.com>
 * @github https://github.com/lihengtt
 */

const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
const { minimatch } = require('minimatch');

// 读取package.json
const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
const { name, version } = packageJson;

console.log(`开始手动打包插件: ${name} v${version}`);

/**
 * 读取并解析.vscodeignore文件
 * @returns {string[]} 排除规则数组
 * @author lihengtt <lihengsir@gmail.com>
 */
function readVscodeIgnore() {
    const ignoreFile = '.vscodeignore';
    if (!fs.existsSync(ignoreFile)) {
        return [];
    }
    
    const content = fs.readFileSync(ignoreFile, 'utf8');
    return content
        .split('\n')
        .map(line => line.trim())
        .filter(line => line && !line.startsWith('#'));
}

/**
 * 检查文件是否应该被排除
 * @param {string} filePath - 文件路径
 * @param {string[]} ignorePatterns - 排除规则
 * @returns {boolean} 是否应该被排除
 * @author lihengtt <lihengsir@gmail.com>
 */
function shouldIgnore(filePath, ignorePatterns) {
    const normalizedPath = filePath.replace(/\\/g, '/');
    
    for (const pattern of ignorePatterns) {
        if (minimatch(normalizedPath, pattern) || 
            minimatch(normalizedPath, pattern.replace(/\*\*$/, '**/*'))) {
            return true;
        }
    }
    return false;
}

// 读取排除规则
const ignorePatterns = readVscodeIgnore();
console.log('✓ 读取.vscodeignore规则:', ignorePatterns.length, '条');

// 1. 确保代码已编译
try {
    console.log('1. 编译TypeScript代码...');
    execSync('npm run compile', { stdio: 'inherit' });
    console.log('✓ 编译完成');
} catch (error) {
    console.error('✗ 编译失败:', error.message);
    process.exit(1);
}

// 2. 检查必要文件
const requiredFiles = [
    'package.json',
    'README.md',
    'out/extension.js'
];

for (const file of requiredFiles) {
    if (!fs.existsSync(file)) {
        console.error(`✗ 缺少必要文件: ${file}`);
        process.exit(1);
    }
}
console.log('✓ 必要文件检查通过');

// 3. 创建临时目录和extension子目录（VSCode插件标准结构）
const tempDir = `temp-${name}-${version}`;
const extensionDir = path.join(tempDir, 'extension');
if (fs.existsSync(tempDir)) {
    fs.rmSync(tempDir, { recursive: true });
}
fs.mkdirSync(tempDir);
fs.mkdirSync(extensionDir);

// 4. 复制文件到extension目录（遵循.vscodeignore规则）
const filesToCopy = [
    'package.json',
    'README.md',
    'CHANGELOG.md',
    'LICENSE'
].filter(file => fs.existsSync(file) && !shouldIgnore(file, ignorePatterns));

// 复制文件到extension目录
filesToCopy.forEach(file => {
    if (!shouldIgnore(file, ignorePatterns)) {
        fs.copyFileSync(file, path.join(extensionDir, file));
        console.log(`✓ 复制文件: ${file}`);
    } else {
        console.log(`✗ 跳过文件: ${file} (被.vscodeignore排除)`);
    }
});

/**
 * 递归复制目录，遵循.vscodeignore规则
 * @param {string} srcDir - 源目录
 * @param {string} destDir - 目标目录
 * @param {string[]} ignorePatterns - 排除规则
 * @author lihengtt <lihengsir@gmail.com>
 */
function copyDirWithIgnore(srcDir, destDir, ignorePatterns) {
    if (shouldIgnore(srcDir, ignorePatterns)) {
        console.log(`✗ 跳过目录: ${srcDir} (被.vscodeignore排除)`);
        return;
    }
    
    if (!fs.existsSync(destDir)) {
        fs.mkdirSync(destDir, { recursive: true });
    }
    
    const items = fs.readdirSync(srcDir);
    
    for (const item of items) {
        const srcPath = path.join(srcDir, item);
        const destPath = path.join(destDir, item);
        const relativePath = path.relative('.', srcPath);
        
        if (shouldIgnore(relativePath, ignorePatterns)) {
            console.log(`✗ 跳过: ${relativePath} (被.vscodeignore排除)`);
            continue;
        }
        
        const stat = fs.statSync(srcPath);
        
        if (stat.isDirectory()) {
            copyDirWithIgnore(srcPath, destPath, ignorePatterns);
        } else {
            fs.copyFileSync(srcPath, destPath);
            console.log(`✓ 复制文件: ${relativePath}`);
        }
    }
}

// 复制out目录到extension目录
if (fs.existsSync('out') && !shouldIgnore('out', ignorePatterns)) {
    copyDirWithIgnore('out', path.join(extensionDir, 'out'), ignorePatterns);
} else if (shouldIgnore('out', ignorePatterns)) {
    console.log('✗ 跳过out目录 (被.vscodeignore排除)');
}

// 复制resources目录到extension目录（如果存在）
if (fs.existsSync('resources') && !shouldIgnore('resources', ignorePatterns)) {
    copyDirWithIgnore('resources', path.join(extensionDir, 'resources'), ignorePatterns);
} else if (shouldIgnore('resources', ignorePatterns)) {
    console.log('✗ 跳过resources目录 (被.vscodeignore排除)');
}

console.log('✓ 文件复制完成');

// 5. 创建VSIX文件（使用PowerShell的Compress-Archive）
const outputFile = `${name}-${version}.vsix`;
const tempZipFile = `${name}-${version}.zip`;
try {
    console.log('5. 创建VSIX文件...');
    
    // 删除已存在的文件
    if (fs.existsSync(outputFile)) {
        fs.unlinkSync(outputFile);
    }
    if (fs.existsSync(tempZipFile)) {
        fs.unlinkSync(tempZipFile);
    }
    
    // 使用PowerShell的Compress-Archive命令创建ZIP文件
    // 注意：VSCode插件需要特定的目录结构，所有文件应该在根目录
    const compressCommand = `powershell -Command "Compress-Archive -Path '${tempDir}\\*' -DestinationPath '${tempZipFile}' -Force"`;
    execSync(compressCommand, { stdio: 'inherit' });
    
    // 重命名ZIP文件为VSIX文件
    fs.renameSync(tempZipFile, outputFile);
    console.log(`✓ 插件打包完成: ${outputFile}`);
} catch (error) {
    console.error('✗ 打包失败:', error.message);
    process.exit(1);
} finally {
    // 清理临时文件
    if (fs.existsSync(tempZipFile)) {
        fs.unlinkSync(tempZipFile);
    }
    // 清理临时目录
    if (fs.existsSync(tempDir)) {
        fs.rmSync(tempDir, { recursive: true });
    }
}

console.log('\n🎉 打包成功!');
console.log(`文件位置: ${path.resolve(outputFile)}`);
console.log('\n安装方法:');
console.log(`code --install-extension ${outputFile}`);